import {
  defineComponent,
  h,
  inject,
  provide,
  type PropType,
  type InjectionKey,
} from 'vue';
import { tableContextInjectKey } from '../table/table';

import { STATES, type State } from '../libs/constant';

import {
  type RenderData,
  type TableColumnConfig,
  type Buttons,
  type ButtonType,
} from '../table-column/table-column';

import { ElButton } from 'element-plus';
import { createNamespace } from '../libs/bem';

type ColumnWrapperProvide = {
  state: State;
};
type ColumnWrapperKey = InjectionKey<ColumnWrapperProvide>;
export const columnWrapperKey: ColumnWrapperKey =
  Symbol('column-wrapper');

// config, data, state
type Props = {
  data: RenderData;
  config: TableColumnConfig;
  state: State;
  emit: (event: ButtonType) => void;
};

const bem = createNamespace('extra-table-operation__button');

// input column
function InputColumn(props: Props) {
  const Text = () => {
    // @ts-ignore
    const text = props.data.row[key];
    return h('span', text);
  };

  const { slot, prop: key } = props.config;
  if (props.state === STATES.view || props.state === STATES.solid) {
    return Text();
  } else if (props.state === STATES.edit) {
    const slotScope = props.data;
    return slot ? slot(slotScope) : Text();
  }
  return '';
}

const defaultButtonNames = {
  add: '添加',
  del: '删除',
  edit: '编辑',
  save: '保存',
  copy: '复制',
};

// operation column
function OperationColumn(props: Props) {
  const { config } = props;
  // console.log('🚀 ~ OperationColumn ~ config:', config);

  // 默认按钮
  const defaultButtons = (buttons: Buttons) => {
    // const config.
    const visiableBtns = config.buttons;
    const stateBtns = new Set(buttons);

    return visiableBtns
      .filter((btn) => stateBtns.has(btn))
      .map((btn) => {
        // console.log('🚀 ~ .map ~ btn:', btn);
        const customButtonConfig = config[btn];

        const { label, ...cfg } = customButtonConfig;
        // console.log('🚀 ~ .map ~ label:', label);

        const buttonLabel = label;
        // label === '' ? defaultButtonNames[btn] : label;

        const onClick = () => {
          props.emit(btn);
        };

        return h(
          ElButton,
          { ...cfg, onClick, class: bem.m(btn) },
          () => buttonLabel
        );
      });
  };

  // 插槽按钮
  const SlotButtons = () => {
    return config.slot?.(props.data) || [];
  };

  // 渲染默认按钮和插槽按钮
  type Btn = (ButtonType | 'slot')[];
  const Buttons = (buttons: Btn) => {
    if (buttons.length === 0) return [];

    const hasSlot = buttons.includes('slot');
    const slotBtns = hasSlot ? SlotButtons() : [];

    const filtered = buttons.filter((btn) => btn !== 'slot');
    const defaultBtns = defaultButtons(filtered);

    return [...defaultBtns, ...slotBtns];
  };

  if (props.state === STATES.view) {
    return Buttons(['edit', 'copy', 'add', 'del', 'slot']);
  } else if (props.state === STATES.edit) {
    return Buttons(['save']);
  } else if (props.state === STATES.solid) {
    return Buttons([]);
  }

  // return '按钮';
}

// extra column
function ExtraColumn(props: Props) {
  const { slot } = props.config;
  if (props.state === STATES.view || props.state === STATES.solid) {
    const slotScope = props.data;
    return slot?.(slotScope) || '';
  } else if (props.state === STATES.edit) {
    const slotScope = props.data;
    return slot?.(slotScope) || '';
  }
  return () => '无';
}

export default defineComponent({
  name: 'extra-table-column-wrapper',
  props: {
    state: { type: String as PropType<State>, default: 'view' },
    data: {
      type: Object as PropType<RenderData>,
      default: () => ({ row: {}, index: -1, data: [] }),
    },
    config: {
      type: Object as PropType<TableColumnConfig>,
      default: () => {},
    },
  },
  emits: ['edit', 'save', 'add', 'del', 'copy'],
  setup($props, { emit, expose }) {
    expose($props.data);
    const tableContext = inject(tableContextInjectKey);

    const context: ColumnWrapperProvide = { state: $props.state };
    provide(columnWrapperKey, context);

    if (!tableContext) return () => '';

    if ($props.config.operation) {
      return () => OperationColumn({ ...$props, emit });
    } else if ($props.config.extra) {
      return ExtraColumn;
    } else {
      return InputColumn;
    }
  },
});
